﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using Shine.Util.Management;

namespace Shine.Util.Net
{
    /// <summary>
    /// 错误信息
    /// </summary>
    public enum ERROR_ID
    {
        /// <summary>
        /// 
        /// </summary>
        ERROR_SUCCESS = 0,  // Success 
        /// <summary>
        /// 
        /// </summary>
        ERROR_BUSY = 170,
        /// <summary>
        /// 
        /// </summary>
        ERROR_MORE_DATA = 234,
        /// <summary>
        /// 
        /// </summary>
        ERROR_NO_BROWSER_SERVERS_FOUND = 6118,
        /// <summary>
        /// 
        /// </summary>
        ERROR_INVALID_LEVEL = 124,
        /// <summary>
        /// 
        /// </summary>
        ERROR_ACCESS_DENIED = 5,
        /// <summary>
        /// 
        /// </summary>
        ERROR_INVALID_PASSWORD = 86,
        /// <summary>
        /// 
        /// </summary>
        ERROR_INVALID_PARAMETER = 87,
        /// <summary>
        /// 
        /// </summary>
        ERROR_BAD_DEV_TYPE = 66,
        /// <summary>
        /// 
        /// </summary>
        ERROR_NOT_ENOUGH_MEMORY = 8,
        /// <summary>
        /// 
        /// </summary>
        ERROR_NETWORK_BUSY = 54,
        /// <summary>
        /// 
        /// </summary>
        ERROR_BAD_NETPATH = 53,
        /// <summary>
        /// 
        /// </summary>
        ERROR_NO_NETWORK = 1222,
        /// <summary>
        /// 
        /// </summary>
        ERROR_INVALID_HANDLE_STATE = 1609,
        /// <summary>
        /// 
        /// </summary>
        ERROR_EXTENDED_ERROR = 1208,
        /// <summary>
        /// 
        /// </summary>
        ERROR_DEVICE_ALREADY_REMEMBERED = 1202,
        /// <summary>
        /// 
        /// </summary>
        ERROR_NO_NET_OR_BAD_PATH = 1203
    }

    /// <summary>
    /// 
    /// </summary>
    public enum RESOURCE_SCOPE
    {
        /// <summary>
        /// 
        /// </summary>
        RESOURCE_CONNECTED = 1,
        /// <summary>
        /// 
        /// </summary>
        RESOURCE_GLOBALNET = 2,
        /// <summary>
        /// 
        /// </summary>
        RESOURCE_REMEMBERED = 3,
        /// <summary>
        /// 
        /// </summary>
        RESOURCE_RECENT = 4,
        /// <summary>
        /// 
        /// </summary>
        RESOURCE_CONTEXT = 5
    }

    /// <summary>
    /// 
    /// </summary>
    public enum RESOURCE_TYPE
    {
        /// <summary>
        /// 
        /// </summary>
        RESOURCETYPE_ANY = 0,
        /// <summary>
        /// 
        /// </summary>
        RESOURCETYPE_DISK = 1,
        /// <summary>
        /// 
        /// </summary>
        RESOURCETYPE_PRINT = 2,
        /// <summary>
        /// 
        /// </summary>
        RESOURCETYPE_RESERVED = 8,
    }

    /// <summary>
    /// 
    /// </summary>
    public enum RESOURCE_USAGE
    {
        /// <summary>
        /// 
        /// </summary>
        RESOURCEUSAGE_CONNECTABLE = 1,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEUSAGE_CONTAINER = 2,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEUSAGE_NOLOCALDEVICE = 4,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEUSAGE_SIBLING = 8,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEUSAGE_ATTACHED = 16,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
    }

    /// <summary>
    /// 
    /// </summary>
    public enum RESOURCE_DISPLAYTYPE
    {
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_GENERIC = 0,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_DOMAIN = 1,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_SERVER = 2,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_SHARE = 3,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_FILE = 4,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_GROUP = 5,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_NETWORK = 6,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_ROOT = 7,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_SHAREADMIN = 8,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_DIRECTORY = 9,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_TREE = 10,
        /// <summary>
        /// 
        /// </summary>
        RESOURCEDISPLAYTYPE_NDSCONTAINER = 11
    }

    /// <summary>
    /// 
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct NETRESOURCE
    {
        /// <summary>
        /// 
        /// </summary>
        public RESOURCE_SCOPE dwScope;
        /// <summary>
        /// 
        /// </summary>
        public RESOURCE_TYPE dwType;
        /// <summary>
        /// 
        /// </summary>
        public RESOURCE_DISPLAYTYPE dwDisplayType;
        /// <summary>
        /// 
        /// </summary>
        public RESOURCE_USAGE dwUsage;

        /// <summary>
        /// 
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpLocalName;

        /// <summary>
        /// 
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpRemoteName;

        /// <summary>
        /// 
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpComment;

        /// <summary>
        /// 
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpProvider;
    }

    /// <summary>
    /// 网络文件服务
    /// </summary>
    public class NetFileService
    {
        /// <summary>
        /// 添加网络文件连接
        /// </summary>
        [DllImport("mpr.dll")]
        public static extern int WNetAddConnection2A(NETRESOURCE[] lpNetResource, string lpPassword, string lpUserName, int dwFlags);

        /// <summary>
        /// 删除文件文件连接
        /// </summary>
        [DllImport("mpr.dll")]
        public static extern int WNetCancelConnection2A(string sharename, int dwFlags, int fForce);

        /// <summary>
        /// 连接到网络文件，成功则返回本地映射的路径。实例：NetFileService.Connect(@"\\126.33.9.171\ToolsISO", "printer", "printer");
        /// </summary>
        /// <param name="remotePath">网络文件路径，如：@"\\126.33.9.171\ToolsISO"</param>
        /// <param name="username">服务器提供的允许连接的用户</param>
        /// <param name="password">连接用户的密码</param>
        /// <returns>成功则返回本地映射的路径</returns>
        public static string Connect(string remotePath,  string username, string password)
        {
            string localPath = GetLogicalDrive();
            if (string.IsNullOrEmpty(localPath) || string.IsNullOrWhiteSpace(localPath)) return "";
            if (localPath.EndsWith("\\")) localPath = localPath.Substring(0, localPath.Trim().Length - 1);
            int result = Connect(remotePath, localPath, username, password);
            if (result == (int)ERROR_ID.ERROR_SUCCESS) return localPath;
            return "";
        }

        /// <summary>
        /// 连接到网络文件,返回连接状态。实例：NetFileService.Connect(@"\\126.33.9.171\ToolsISO", "printer", "printer");
        /// </summary>
        /// <param name="remotePath">网络文件路径，如：@"\\126.33.9.171\ToolsISO"</param>
        /// <param name="localPath">本地映射的路径</param>
        /// <param name="username">服务器提供的允许连接的用户</param>
        /// <param name="password">连接用户的密码</param>
        /// <param name="disconn">是否断开之前的连接，默认为true，断开</param>
        /// <returns>返回连接状态，0表示连接正常，其他请查看ERROR_ID</returns>
        public static int Connect(string remotePath, string localPath, string username, string password, bool disconn = true)
        {
            NETRESOURCE[] share_driver = new NETRESOURCE[1];
            share_driver[0].dwScope = RESOURCE_SCOPE.RESOURCE_GLOBALNET;
            share_driver[0].dwType = RESOURCE_TYPE.RESOURCETYPE_ANY;
            share_driver[0].dwDisplayType = RESOURCE_DISPLAYTYPE.RESOURCEDISPLAYTYPE_SHARE;
            share_driver[0].dwUsage = RESOURCE_USAGE.RESOURCEUSAGE_CONNECTABLE;
            share_driver[0].lpLocalName = localPath;
            share_driver[0].lpRemoteName = remotePath;
            if (Directory.Exists(localPath))
            {
                if (disconn)
                    Disconnect(localPath);
                else
                    return (int)ERROR_ID.ERROR_SUCCESS;
            }
            //启动Workstation服务
            OSHelper.StartService("LanmanWorkstation");
            int result = WNetAddConnection2A(share_driver, password, username, 1);
            return result;
        }

        /// <summary>
        /// 取消连接
        /// </summary>
        public static int Disconnect(string localpath)
        {
            return WNetCancelConnection2A(localpath, 1, 1);
        }

        /// <summary>
        /// 获取本地映射的盘符
        /// </summary>
        /// <returns></returns>
        private static string GetLogicalDrive()
        {
            string[] dirs = new string[] { "Z:\\", "Y:\\", "X:\\", "W:\\", "V:\\", "U:\\", "T:\\", "S:\\", "R:\\", "Q:\\", "P:\\", "O:\\", "N:\\", "M:\\", "L:\\", "K:\\", "J:\\", "I:\\", "H:\\", "G:\\", "F:\\", "E:\\", "D:\\", "C:\\", "B:\\", "A:\\" };
            string[] paths = Directory.GetLogicalDrives();
            foreach (string d in dirs)
            {
                string s = paths.FirstOrDefault(t => t.Equals(d, StringComparison.CurrentCultureIgnoreCase));
                if (string.IsNullOrEmpty(s) || string.IsNullOrWhiteSpace(s)) return d;
            }
            return "";
        }
    }
}
